home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 33
/
Amiga Format AFCD33 (Issue 117, Dec 1998).iso
/
+system+
/
tools
/
expert
/
snoopdos
/
snoopdos_source
/
settings.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-09-07
|
52KB
|
1,907 lines
/*
* SETTINGS.C vi:ts=4
*
* Copyright (c) Eddy Carroll, September 1994.
*
* This module handles all the command parsing for tooltypes, command
* line options, config files, AREXX, etc.
*/
#include "system.h"
#include "snoopdos.h"
extern char Version[]; /* From Snoopdos.c */
extern char CommodityTitle[]; /* From Snoopdos.c */
char ConfigID[] = "<SnoopDos Settings>";
ULONG UpdateFlags; /* Shows what settings were changed */
struct MsgPort *RemoteReplyPort; /* Used when talking to b/g SnoopDos */
/*
* Now the result codes returned by our simple command interpreter
*/
typedef enum {
EXEC_FAIL, /* The command failed for some reason */
EXEC_OKAY, /* The command succeeded */
EXEC_UNKNOWN, /* The command wasn't recognised */
EXEC_NOPARAM /* The command was missing a parameter */
} ExecEnum;
/*
* Now let's define the commands we understand.
*/
#define CMD_UNKNOWN -1
#define CMD_NOPARAM -2
typedef enum {
CMD_END,
/*
* Options within function requester. Note that these MUST correspond
* exactly with the first set of enums in SNOOPDOS.H for GID_???!
*/
CMD_FINDPORT,
CMD_FINDRESIDENT,
CMD_FINDSEMAPHORE,
CMD_FINDTASK,
CMD_LOCKSCREEN,
CMD_OPENDEVICE,
CMD_OPENFONT,
CMD_OPENLIBRARY,
CMD_OPENRESOURCE,
CMD_READTOOLTYPES,
CMD_SENDREXX,
CMD_CHANGEDIR,
CMD_DELETE,
CMD_EXECUTE,
CMD_GETVAR,
CMD_LOADSEG,
CMD_LOCK,
CMD_MAKEDIR,
CMD_MAKELINK,
CMD_OPEN,
CMD_RENAME,
CMD_RUNCOMMAND,
CMD_SETVAR,
CMD_DOSSYSTEM, /* CMD_SYSTEM is defined in dos/dosextens.h */
CMD_DUMMY1,
CMD_DUMMY2,
CMD_DUMMY3,
CMD_DUMMY4,
CMD_DUMMY5,
CMD_ONLYSHOWFAILS,
CMD_SHOWCLI,
CMD_SHOWFULLPATH,
CMD_USEDEVICENAME,
CMD_MONITORPACKETS,
CMD_MONALLPACKETS,
CMD_MONROMCALLS,
CMD_IGNORESHELL,
#define MAX_BOOL_CMD CMD_IGNORESHELL
CMD_MATCHNAME,
/*
* General commands
*/
CMD_LOADSETTINGS,
CMD_SAVESETTINGS,
CMD_LOADDEFSETTINGS,
CMD_SAVEDEFSETTINGS,
CMD_SETTINGS,
CMD_FUNCTIONS,
CMD_LANGUAGE,
CMD_CLEARBUFFER,
CMD_WINDOWWIDTH,
CMD_HELP,
CMD_COPYWINDOW,
CMD_COPYBUFFER,
CMD_SAVEWINDOW,
CMD_SAVEBUFFER,
CMD_SHOW,
CMD_HIDE,
CMD_OPENFORMAT,
CMD_OPENFUNCTION,
CMD_OPENSETUP,
CMD_CLOSEFORMAT,
CMD_CLOSEFUNCTION,
CMD_CLOSESETUP,
CMD_QUIT,
CMD_PAUSE,
CMD_UNPAUSE,
CMD_DISABLE,
CMD_ENABLE,
CMD_SINGLESTEP,
CMD_OPENLOG,
CMD_APPENDLOG,
CMD_OPENSERIALLOG,
CMD_CLOSELOG,
CMD_ADDLOG,
CMD_FLUSHLOG,
CMD_SCROLLUP,
CMD_SCROLLDOWN,
CMD_GOTO,
/*
* General settings
*/
CMD_PATCHRAMLIB,
CMD_STACKLIMIT,
CMD_ICONPOS,
CMD_SHOWGADGETS,
CMD_HIDEGADGETS,
CMD_AUTOOPEN,
CMD_DISABLEWHENHIDDEN,
CMD_SHOWSTATUS,
CMD_HIDESTATUS,
CMD_CREATEICONS,
CMD_TEXTSPACING,
CMD_SIMPLEREFRESH,
CMD_SMARTREFRESH,
CMD_LEFTALIGNED,
CMD_RIGHTALIGNED,
CMD_ROWQUALIFIER,
CMD_MAINPOS,
CMD_MAINSIZE,
CMD_FUNCPOS,
CMD_FORMPOS,
CMD_SETPOS,
CMD_TASKPRI,
CMD_CXPRI,
/*
* Options within setup requester
*/
CMD_HIDEMETHOD,
CMD_SCREENTYPE,
CMD_BUFFERSIZE,
CMD_LOGMODE,
CMD_FILEIOTYPE,
CMD_FORMAT,
CMD_LOGFORMAT,
CMD_HOTKEY,
CMD_SCREENNAME,
CMD_LOGNAME,
CMD_WINDOWFONT,
CMD_BUFFERFONT,
NUMCOMMANDS
} COMMAND_ID;
/*
* Now associate a command string with each of these identifiers
*/
struct Command {
short cmdid; /* Command ID */
short changemask; /* Which group of settings will change */
short numparms; /* Min number of parameters (0 or more) */
char *name; /* Command name */
} CommandTable[] = {
/*
* In alphabetical order, for quick reference
*/
CMD_ADDLOG, SET_NONE, 1, "AddLog",
CMD_APPENDLOG, SET_NONE, 1, "AppendLog",
CMD_AUTOOPEN, SET_MAIN, 0, "AutoOpen",
CMD_BUFFERFONT, SET_SETUP, 1, "BufferFont",
CMD_BUFFERSIZE, SET_SETUP, 1, "BufferSize",
CMD_CHANGEDIR, SET_FUNC, 0, "ChangeDir",
CMD_CLEARBUFFER, SET_FUNC, 0, "ClearBuffer",
CMD_CLOSEFORMAT, SET_NONE, 0, "CloseFormat",
CMD_CLOSEFUNCTION, SET_NONE, 0, "CloseFunction",
CMD_CLOSELOG, SET_NONE, 0, "CloseLog",
CMD_CLOSESETUP, SET_NONE, 0, "CloseSetup",
CMD_COPYBUFFER, SET_NONE, 0, "CopyBuffer",
CMD_COPYWINDOW, SET_NONE, 0, "CopyWindow",
CMD_CREATEICONS, SET_MAIN, 0, "CreateIcons",
CMD_HOTKEY, SET_SETUP, 1, "CX_PopKey",
CMD_SHOW, SET_NONE, 0, "CX_Popup",
CMD_CXPRI, SET_NONE, 1, "CX_Priority",
CMD_DELETE, SET_FUNC, 0, "Delete",
CMD_DISABLE, SET_NONE, 0, "Disable",
CMD_DISABLEWHENHIDDEN, SET_MAIN, 0, "DisableWhenHidden",
CMD_ENABLE, SET_NONE, 0, "Enable",
CMD_EXECUTE, SET_FUNC, 0, "Execute",
CMD_FILEIOTYPE, SET_SETUP, 1, "FileIOType",
CMD_FINDPORT, SET_FUNC, 0, "FindPort",
CMD_FINDRESIDENT, SET_FUNC, 0, "FindResident",
CMD_FINDSEMAPHORE, SET_FUNC, 0, "FindSemaphore",
CMD_FINDTASK, SET_FUNC, 0, "FindTask",
CMD_FLUSHLOG, SET_NONE, 0, "FlushLog",
CMD_FORMAT, SET_SETUP, 1, "Format",
CMD_FORMPOS, SET_MAIN, 1, "FormatWindowPos",
CMD_FUNCTIONS, SET_FUNC, 1, "Functions",
CMD_FUNCPOS, SET_MAIN, 1, "FunctionWindowPos",
CMD_GETVAR, SET_FUNC, 0, "GetVar",
CMD_GOTO, SET_NONE, 1, "GotoLine",
CMD_HELP, SET_NONE, 0, "Help",
CMD_HIDE, SET_NONE, 0, "Hide",
CMD_HIDEGADGETS, SET_MAIN, 0, "HideGadgets",
CMD_HIDEMETHOD, SET_SETUP, 1, "HideMethod",
CMD_HIDESTATUS, SET_MAIN, 0, "HideStatus",
CMD_HOTKEY, SET_SETUP, 1, "HotKey",
CMD_ICONPOS, SET_MAIN, 1, "IconPos",
CMD_IGNORESHELL, SET_FUNC, 0, "IgnoreShell",
CMD_LANGUAGE, SET_NONE, 1, "Language",
CMD_LEFTALIGNED, SET_MAIN, 0, "LeftAligned",
CMD_LOADDEFSETTINGS, SET_NONE, 0, "LoadDefSettings",
CMD_LOADSEG, SET_FUNC, 0, "LoadSeg",
CMD_LOADSETTINGS, SET_NONE, 1, "LoadSettings",
CMD_LOCK, SET_FUNC, 0, "Lock",
CMD_LOCKSCREEN, SET_FUNC, 0, "LockScreen",
CMD_LOGFORMAT, SET_SETUP, 1, "LogFormat",
CMD_LOGMODE, SET_SETUP, 1, "LogMode",
CMD_LOGNAME, SET_SETUP, 1, "LogName",
CMD_MAINPOS, SET_MAIN, 1, "MainWindowPos",
CMD_MAINSIZE, SET_MAIN, 1, "MainWindowSize",
CMD_MAKEDIR, SET_FUNC, 0, "MakeDir",
CMD_MAKELINK, SET_FUNC, 0, "MakeLink",
CMD_MATCHNAME, SET_FUNC, 1, "MatchName",
CMD_MONITORPACKETS, SET_FUNC, 0, "MonitorPackets",
CMD_MONROMCALLS, SET_FUNC, 0, "MonitorROMCalls",
CMD_ONLYSHOWFAILS, SET_FUNC, 0, "OnlyShowFails",
CMD_OPEN, SET_FUNC, 0, "Open",
CMD_OPENDEVICE, SET_FUNC, 0, "OpenDevice",
CMD_OPENFONT, SET_FUNC, 0, "OpenFont",
CMD_OPENFORMAT, SET_NONE, 0, "OpenFormat",
CMD_OPENFUNCTION, SET_NONE, 0, "OpenFunction",
CMD_OPENLIBRARY, SET_FUNC, 0, "OpenLibrary",
CMD_OPENLOG, SET_NONE, 1, "OpenLog",
CMD_OPENRESOURCE, SET_FUNC, 0, "OpenResource",
CMD_OPENSERIALLOG, SET_NONE, 0, "OpenSerialLog",
CMD_OPENSETUP, SET_NONE, 0, "OpenSetup",
CMD_MONALLPACKETS, SET_FUNC, 0, "PacketDebugger",
CMD_PATCHRAMLIB, SET_NONE, 0, "PatchRamLib",
CMD_PAUSE, SET_NONE, 0, "Pause",
CMD_QUIT, SET_NONE, 0, "Quit",
CMD_READTOOLTYPES, SET_FUNC, 0, "ReadToolTypes",
CMD_RENAME, SET_FUNC, 0, "Rename",
CMD_RIGHTALIGNED, SET_MAIN, 0, "RightAligned",
CMD_ROWQUALIFIER, SET_MAIN, 1, "RowQualifier",
CMD_RUNCOMMAND, SET_FUNC, 0, "RunCommand",
CMD_SAVEBUFFER, SET_NONE, 1, "SaveBuffer",
CMD_SAVEDEFSETTINGS, SET_NONE, 0, "SaveDefSettings",
CMD_SAVESETTINGS, SET_NONE, 1, "SaveSettings",
CMD_SAVEWINDOW, SET_NONE, 1, "SaveWindow",
CMD_SCREENNAME, SET_SETUP, 1, "ScreenName",
CMD_SCREENTYPE, SET_SETUP, 1, "ScreenType",
CMD_SCROLLDOWN, SET_NONE, 1, "ScrollDown",
CMD_SCROLLUP, SET_NONE, 1, "ScrollUp",
CMD_SENDREXX, SET_FUNC, 0, "SendRexx",
CMD_SETTINGS, SET_NONE, 1, "Settings",
CMD_SETPOS, SET_MAIN, 1, "SetupWindowPos",
CMD_SETVAR, SET_FUNC, 0, "SetVar",
CMD_SHOW, SET_NONE, 0, "Show",
CMD_SHOWCLI, SET_FUNC, 0, "ShowCLI",
CMD_SHOWFULLPATH, SET_FUNC, 0, "ShowFullPath",
CMD_SHOWGADGETS, SET_MAIN, 0, "ShowGadgets",
CMD_SHOWSTATUS, SET_MAIN, 0, "ShowStatus",
CMD_SIMPLEREFRESH, SET_MAIN, 0, "SimpleRefresh",
CMD_SINGLESTEP, SET_NONE, 0, "SingleStep",
CMD_SMARTREFRESH, SET_MAIN, 0, "SmartRefresh",
CMD_STACKLIMIT, SET_MAIN, 1, "StackLimit",
CMD_DOSSYSTEM, SET_FUNC, 0, "System",
CMD_TASKPRI, SET_NONE, 1, "TaskPri",
CMD_TEXTSPACING, SET_MAIN, 1, "TextSpacing",
CMD_UNPAUSE, SET_NONE, 0, "Unpause",
CMD_USEDEVICENAME, SET_FUNC, 0, "UseDeviceNames",
CMD_WINDOWFONT, SET_SETUP, 1, "WindowFont",
CMD_WINDOWWIDTH, SET_NONE, 1, "WindowWidth",
CMD_END, 0, 0, NULL
};
#define NUM_CMDNAMES (sizeof(CommandTable) / sizeof(CommandTable[0]))
char *CmdNames[NUMCOMMANDS]; /* Map command IDs back to name strings */
char *Names_HideMethod[] = { "Invisible", "Iconify", "ToolsMenu",
"None", NULL };
char *Names_ScreenType[] = { "Default", "Front", "Named", NULL };
char *Names_LogMode[] = { "Prompt", "Append", "Overwrite",
"SerialPort", NULL };
char *Names_FileIOType[] = { "Automatic", "Immediate", "Buffered", NULL };
char *Names_Functions[] = { "All", "None", "AllDos", "NoDos",
"AllSystem", "NoSystem", NULL };
char *Names_RowQualifier[] = { "Ignore", "None", "Shift", "Alt", "Ctrl",
"All", NULL };
typedef enum {
FUNC_ALL, FUNC_NONE, FUNC_ALLDOS, FUNC_NODOS,
FUNC_ALLSYSTEM, FUNC_NOSYSTEM
} FuncTypes;
/*
* InitSettings()
*
* Initialises variables associated with settings. For now, this
* just means the mapping array that maps command IDs to command
* names. This makes it easier to write out the configuration file.
*/
void InitSettings(void)
{
struct Command *cmd;
int i;
for (i = 0; i < NUMCOMMANDS; i++)
CmdNames[i] = ""; /* Make sure non-cmds initialised to safe value */
for (cmd = CommandTable; cmd->cmdid != CMD_END; cmd++)
CmdNames[cmd->cmdid] = cmd->name;
}
/*
* MatchParam(&var, param, keywords)
*
* Searches the keyword list for a match with param and stores
* the result in the given variable. If no match is found, var
* is not altered and returns EXEC_FAIL, else returns EXEC_OKAY.
*/
int MatchParam(unsigned char *var, char *param, char **keywords)
{
int i;
for (i = 0; keywords[i]; i++) {
if (stricmp(param, keywords[i]) == 0) {
*var = i;
return (EXEC_OKAY);
}
}
return (EXEC_FAIL);
}
/*
* ParseFontName(fontspec, fontname, &fontsize)
*
* Parses the font spec in fontspec, which is of the form
* "fontname size" or "fontname.font size" or "fontname.size",
* into two parts.
*
* The bulk of the name (plus a .font suffix) is copied into fontname.
* The size of the font is copied into fontsize. In the event of a parse
* error, EXEC_FAIL is returned and no alteration is made to fontname
* or fontsize. For success, EXEC_OKAY is returned.
*
* Note that the contents of the string pointed to by fontspec may be
* altered. If fontspec is "default" then a fontsize of 0 is returned
* to indicate that SnoopDos should use the system default fonts.
*/
int ParseFontName(char *fontspec, char *fontname, USHORT *fontsize)
{
char *p;
int size;
/*
* First, see if we can find a dot specifier. Anything before
* the dot is a font name.
*/
if (stricmp(fontspec, "default") == 0) {
strcpy(fontname, fontspec);
*fontsize = 0;
return (EXEC_OKAY);
}
p = strchr(fontspec, '.');
if (p) {
*p++ = '\0';
if (strnicmp(p, "font", 4) == 0)
p += 4;
} else {
p = strchr(fontspec, ' ');
if (!p)
return (EXEC_FAIL);
*p++ = '\0';
}
while (*p == ' ' || *p == '.')
p++;
size = atoi(p);
if (size == 0)
return (EXEC_FAIL);
strcpy(fontname, fontspec);
strcat(fontname, ".font");
*fontsize = size;
return (EXEC_OKAY);
}
/*
* ParseTwoNums(param, &num1, &num2)
*
* Parses the given param string, assumed to be in the form "x1,x2"
* and stores the two numbers in the given variables. If either number
* is invalid, then no change is made to either number and EXEC_FAIL
* is returned, else EXEC_OKAY is returned.
*
* The string pointed to by param may be altered.
*/
int ParseTwoNums(char *param, WORD *num1, WORD *num2)
{
char *p;
p = strchr(param, ',');
if (!p)
return (EXEC_FAIL);
*p++ = '\0';
while (*p == ' ')
p++;
if (*param < '-' || *param > '9' || *p < '-' || *p > '9')
return (EXEC_FAIL);
*num1 = atoi(param);
*num2 = atoi(p);
return (EXEC_OKAY);
}
/*
* cid = ParseCommand(cmdline, cmdname, param, &boolvalue, &cmd)
*
* Copies the cmdline into two separate strings, one for the
* command name and one for the parameters. Bool is initalised
* to 0 or 1, according to the default value of the parameter
* (1 if Yes,True,On, 0 if No, False, Off, or if the command
* is prefixed by the word No).
*
* cmd points to the command structure for this command.
*
* cid is the command ID that matches the command, CMD_END for
* a null command, CMD_UNKNOWN for an unrecognised command,
* and CMD_NOPARAM for a known command with too few parameters.
* If CMD_NOPARAM is returned, cmdname and &cmd will be initialised
* to the command that was matched.
*
*/
int ParseCommand(char *cmdline, char *cmdname, char *param, int *boolvalue,
struct Command **pcmd)
{
struct Command *cmd;
int cid;
char *p;
char *q;
if (!cmdline)
return (CMD_END);
/*
* First, copy just the command header
*/
for (p = cmdline; *p == ' ' || *p == '\t'; p++)
;
q = cmdname;
while (*p && *p != ';' && *p != '=' &&
*p != ' ' && *p != '\t' && *p != '\n')
*q++ = *p++;
*q = '\0';
if (!*cmdname)
return (CMD_END); /* Skip over blank lines and comments */
/*
* Now skip over any whitespace until we find the next parameter
*/
while (*p == ' ' || *p == '=' || *p == '\t' || *p == '\n')
p++;
q = param;
if (*p == '\"') {
/*
* Got a quoted string .. copy everything inside the quotes
*/
p++;
while (*p && *p != '\n' && *p != '\"')
*q++ = *p++;
*q = '\0';
} else {
/*
* Not a quoted string .. copy everything to end of line
* or semicolon, excluding any trailing spaces.
*/
while (*p && *p != '\n' && *p != ';')
*q++ = *p++;
while (--q >= param && (*q == ' ' || *q == '\n' || *q == '\t'))
;
*++q = '\0';
if (q == param)
q = NULL;
}
/*
* Finally, if we got no specific parameter, check if the
* command beings with "No" -- if so, then assume the
* parameter is boolean instead and set accordingly
*/
*boolvalue = 1;
if (!q) {
if (strnicmp(cmdname, "no", 2) == 0) {
*boolvalue = 0;
cmdname += 2;
}
} else {
if ( stricmp(param, "off") == 0 ||
stricmp(param, "no") == 0 ||
stricmp(param, "0") == 0)
{
*boolvalue = 0;
}
}
/*
* Now locate identifier which matches command
*/
for (cmd = CommandTable; cmd->cmdid != CMD_END; cmd++)
if (stricmp(cmd->name, cmdname) == 0)
break;
cid = cmd->cmdid;
if (cid == CMD_END)
return (CMD_UNKNOWN);
*pcmd = cmd;
if (cmd->numparms > 0 && !q)
return (CMD_NOPARAM);
return (cid);
}
/*
* ExecCommand(cmd, mode, set)
*
* Interprets the given command and executes it. cmd points to the
* command string which is one of the following forms:
*
* command
* command=value
* setting
* nosetting
* setting=on
* setting=off
*
* The "setting" commands are used to toggle the various boolean
* settings that can be accessed through the requesters.
*
* mode is the place where the setting occurs. This will be one of
* MODE_REXX, MODE_SETTINGS, MODE_CMDLINE or MODE_TOOLTYPE, depending
* on where the command being executed originated from. In some cases,
* this affects how the command is executed.
*
* set is a pointer to a copy of the current settings (NOT the actual
* settings!) This copy is updated to reflect the changes. The intention
* is that you can call ExecCommand() multiple times with the same
* copy, and then finally call InstallSettings() at the end to make
* the new settings take effect. This way, only a single update
* needs to be done for an entire configuration file.
*
* The global UpdateFlags should be initialised to 0 before the first
* call, and then passed to InstallSettings() at the end -- it will
* contain the appropriate combination of SET_??? flags to indicate
* what settings actually changed.
*
* Returns EXEC_OKAY for success, EXEC_FAIL for failure, or EXEC_UNKNOWN
* if the command couldn't be understood.
*/
int ExecCommand(char *cmdline, int mode, Settings *set)
{
APTR oldwinptr = *TaskWindowPtr;
struct Command *cmd; /* Pointer to command */
char cmdname[100]; /* Storage area for command */
char parambuf[100]; /* Storage for parameters */
char *param; /* Pointer to parameters */
int boolvalue; /* for settings: either 1 or 0 */
int success = EXEC_OKAY; /* Default return value */
int cid;
int val;
cid = ParseCommand(cmdline, cmdname, parambuf, &boolvalue, &cmd);
switch (cid) {
case CMD_END: return (EXEC_OKAY);
case CMD_UNKNOWN: return (EXEC_UNKNOWN);
case CMD_NOPARAM: return (EXEC_NOPARAM);
}
UpdateFlags |= cmd->changemask;
param = parambuf;
/*
* Okay, got ourselves a valid command. Now interpret it.
*/
if (cid <= MAX_BOOL_CMD) {
/*
* Got a boolean option to update
*/
set->Func.Opts[cid] = boolvalue;
return (EXEC_OKAY);
}
switch (cid) {
case CMD_LANGUAGE:
strcpy(Language, param);
break;
case CMD_SETTINGS:
strcpy(DefaultConfigName, param);
strcpy(ConfigFileName, param);
break;
case CMD_LOADDEFSETTINGS:
success = LoadConfig(DefaultConfigName, mode, set);
break;
case CMD_SAVEDEFSETTINGS:
success = SaveConfig(DefaultConfigName, SAVE_NOICON);
break;
case CMD_LOADSETTINGS:
success = LoadConfig(param, mode, set);
break;
case CMD_SAVESETTINGS:
success = SaveConfig(param, SAVE_ICON);
break;
case CMD_HELP:
{
char helpmsg[100];
/*
* We install the current settings first, to ensure
* that things like the default public screen are
* correctly set up before we open help.
*/
if (UpdateFlags) {
InstallSettings(set, UpdateFlags);
UpdateFlags = 0;
*set = CurSettings;
}
if (*param)
mysprintf(helpmsg, "LINK %s\n", param);
else
strcpy(helpmsg, MSG(MSG_LINK_MAIN));
ShowAGuide(helpmsg);
break;
}
case CMD_SHOWGADGETS: set->ShowGadgets = boolvalue; break;
case CMD_HIDEGADGETS: set->ShowGadgets = !boolvalue; break;
case CMD_SHOWSTATUS: set->ShowStatus = boolvalue; break;
case CMD_HIDESTATUS: set->ShowStatus = !boolvalue; break;
case CMD_AUTOOPEN: set->AutoOpenMain = boolvalue; break;
case CMD_DISABLEWHENHIDDEN: set->DisableWhenHidden = boolvalue; break;
case CMD_CREATEICONS: set->MakeIcons = boolvalue; break;
case CMD_SIMPLEREFRESH: set->SimpleRefresh = boolvalue; break;
case CMD_SMARTREFRESH: set->SimpleRefresh = !boolvalue; break;
case CMD_LEFTALIGNED: set->RightAlign = !boolvalue; break;
case CMD_RIGHTALIGNED: set->RightAlign = boolvalue; break;
case CMD_TEXTSPACING:
val = *param - '0';
if (val < 0 || val > 2)
return (EXEC_FAIL);
set->TextSpacing = val;
break;
case CMD_ROWQUALIFIER:
return MatchParam(&set->RowQualifier, param, Names_RowQualifier);
case CMD_FUNCTIONS:
/*
* Set or clear the function table according to the
* parameters
*/
{
unsigned char functype;
int low = FIRST_SYS_GADGET;
int high = LAST_DOS_GADGET;
int bool = 1;
int i;
if (MatchParam(&functype, param, Names_Functions) == EXEC_FAIL)
return (EXEC_FAIL);
switch (functype) {
case FUNC_ALL: break; /* Use defaults */
case FUNC_NONE: bool = 0; break;
case FUNC_ALLDOS: low = FIRST_DOS_GADGET; break;
case FUNC_NODOS: low = FIRST_DOS_GADGET; bool = 0; break;
case FUNC_ALLSYSTEM: high = LAST_SYS_GADGET; break;
case FUNC_NOSYSTEM: high = LAST_SYS_GADGET; bool = 0; break;
}
for (i = low; i <= high; i++)
set->Func.Opts[i] = bool;
break;
}
case CMD_COPYWINDOW:
DisableAllWindows();
success = SaveBuffer(SAVEBUF_WINDOW, SAVEBUF_CLIPBOARD,
SAVEBUF_OVERWRITE);
EnableAllWindows();
break;
/* Fallthrough */
case CMD_COPYBUFFER:
DisableAllWindows();
success = SaveBuffer(SAVEBUF_ALL, SAVEBUF_CLIPBOARD,
SAVEBUF_OVERWRITE);
EnableAllWindows();
break;
case CMD_SAVEWINDOW:
DisableAllWindows();
success = SaveBuffer(SAVEBUF_WINDOW, param, SAVEBUF_OVERWRITE);
EnableAllWindows();
break;
case CMD_SAVEBUFFER:
DisableAllWindows();
success = SaveBuffer(SAVEBUF_ALL, param, SAVEBUF_OVERWRITE);
EnableAllWindows();
break;
case CMD_CXPRI:
CommodityPriority = atoi(param);
if (HotKeyActive) {
/*
* Reinstall commodity to take advantage of the
* updated priority
*/
InstallHotKey(CurSettings.Setup.HotKey);
}
break;
case CMD_ICONPOS:
success = ParseTwoNums(param, &set->IconPosLeft, &set->IconPosTop);
break;
case CMD_HIDE:
case CMD_SHOW:
/*
* Install all settings modified so far
*/
if (UpdateFlags) {
InstallSettings(set, UpdateFlags);
UpdateFlags = 0;
*set = CurSettings;
}
/*
* We allow both of these so that NOSHOW and NOHIDE
* will also work, as well as SHOW=YES and HIDE=NO
* In particular, CX_Popup=Yes and CX_Popup=No will
* work as expected.
*/
if ((boolvalue && cid == CMD_SHOW) ||
(!boolvalue && cid == CMD_HIDE)) {
/*
* Showing SnoopDos. Install all settings changed
* so far, so that they'll be in effect when the window
* is open (especially font changes)
*/
success = ShowSnoopDos();
HideOnStartup = 0;
} else {
HideSnoopDos();
HideOnStartup = 1;
}
break;
case CMD_OPENFORMAT:
case CMD_OPENFUNCTION:
case CMD_OPENSETUP:
/*
* Install the current settings, so that they take
* effect before the window is opened (font changes
* and the like).
*/
if (UpdateFlags) {
InstallSettings(set, UpdateFlags);
UpdateFlags = 0;
*set = CurSettings;
}
switch (cid) {
case CMD_OPENFORMAT: success = OpenFormatWindow();
break;
case CMD_OPENFUNCTION: success = OpenFunctionWindow();
break;
case CMD_OPENSETUP: success = OpenSettingsWindow();
break;
}
break;
case CMD_CLOSEFORMAT: CloseFormatWindow(); break;
case CMD_CLOSEFUNCTION: CloseFunctionWindow(); break;
case CMD_CLOSESETUP: CloseSettingsWindow(); break;
case CMD_QUIT:
if (mode != MODE_SETTINGS)
QuitFlag = 1;
else
success = EXEC_FAIL;
break;
case CMD_SINGLESTEP: SingleStep(); break;
case CMD_PAUSE:
case CMD_DISABLE:
case CMD_UNPAUSE:
case CMD_ENABLE:
/*
* We treat these four together so we can account for
* all the different boolean verisons (Disable=Yes,
* Enable=No, UnPause=Yes, Pause=No, etc.)
*/
if ((cid == CMD_DISABLE && boolvalue) ||
(cid == CMD_ENABLE && !boolvalue))
{
SetMonitorMode(MONITOR_DISABLED);
} else if ((cid == CMD_PAUSE && boolvalue) ||
(cid == CMD_UNPAUSE && !boolvalue))
{
SetMonitorMode(MONITOR_PAUSED);
} else
SetMonitorMode(MONITOR_NORMAL);
break;
case CMD_OPENLOG:
case CMD_APPENDLOG:
/*
* For these two, we make any current settings take effect,
* so that things like default file buffering mode will be
* activated.
*/
if (UpdateFlags) {
InstallSettings(set, UpdateFlags);
UpdateFlags = 0;
*set = CurSettings;
}
if (cid == CMD_OPENLOG)
success = OpenLog(LOGMODE_OVERWRITE, param);
else
success = OpenLog(LOGMODE_APPEND, param);
break;
case CMD_OPENSERIALLOG:
success = OpenLog(LOGMODE_SERIALPORT, param);
break;
case CMD_CLOSELOG:
CloseLog();
break;
case CMD_ADDLOG:
/*
* Output a user comment to the specified logfile
*/
strcat(param, "\n");
WriteLog(param);
break;
case CMD_FLUSHLOG:
/*
* Flush the current contents of the log
*/
WriteLog(NULL);
break;
case CMD_HIDEMETHOD: return MatchParam(&set->Setup.HideMethod, param,
Names_HideMethod);
case CMD_SCREENTYPE: return MatchParam(&set->Setup.ScreenType, param,
Names_ScreenType);
case CMD_LOGMODE: return MatchParam(&set->Setup.LogMode, param,
Names_LogMode);
case CMD_FILEIOTYPE: return MatchParam(&set->Setup.FileIOType, param,
Names_FileIOType);
case CMD_BUFFERSIZE:
val = atoi(param);
if (val > 1)
set->Setup.BufferSize = val;
break;
case CMD_WINDOWWIDTH:
SetMainWindowWidth(atoi(param)); /* 0 is supported */
break;
case CMD_STACKLIMIT:
if (*param < '0' || *param > '9')
return (EXEC_FAIL);
set->StackLimit = atoi(param);
break;
case CMD_PATCHRAMLIB: break; /* Actually handled in ParseStartup */
case CMD_FORMAT: strcpy(set->Setup.BufferFormat, param); break;
case CMD_LOGFORMAT:
if (stricmp(param, "none") == 0)
*param = '\0';
strcpy(set->Setup.LogfileFormat, param); break;
break;
case CMD_HOTKEY: strcpy(set->Setup.HotKey, param); break;
case CMD_SCREENNAME: strcpy(set->Setup.ScreenName, param); break;
case CMD_LOGNAME: strcpy(set->Setup.LogFile, param);
*TaskWindowPtr = (APTR)-1;
if (IsFileSystem(set->Setup.LogFile))
strcpy(ChosenLogName, param);
*TaskWindowPtr = oldwinptr;
break;
case CMD_MATCHNAME: strcpy(set->Func.Pattern, param); break;
case CMD_WINDOWFONT:
return ParseFontName(param, set->Setup.WindowFont,
&set->Setup.WinFontSize);
case CMD_BUFFERFONT:
return ParseFontName(param, set->Setup.BufferFont,
&set->Setup.BufFontSize);
case CMD_MAINSIZE:
success = ParseTwoNums(param, &set->MainWinWidth,
&set->MainWinHeight);
if (success && mode != MODE_SETTINGS && MainWindow)
SizeWindow(MainWindow, set->MainWinWidth - MainWindow->Width,
set->MainWinHeight- MainWindow->Height);
break;
case CMD_MAINPOS:
success = ParseTwoNums(param, &set->MainWinLeft, &set->MainWinTop);
if (success && mode != MODE_SETTINGS && MainWindow)
MoveWindow(MainWindow, set->MainWinLeft - MainWindow->LeftEdge,
set->MainWinTop - MainWindow->TopEdge);
break;
case CMD_FORMPOS:
success = ParseTwoNums(param, &set->FormWinLeft, &set->FormWinTop);
if (success && mode != MODE_SETTINGS && FormWindow)
MoveWindow(FormWindow, set->FormWinLeft - FormWindow->LeftEdge,
set->FormWinTop - FormWindow->TopEdge);
break;
case CMD_FUNCPOS:
success = ParseTwoNums(param, &set->FuncWinLeft, &set->FuncWinTop);
if (success && mode != MODE_SETTINGS && FuncWindow)
MoveWindow(FuncWindow, set->FuncWinLeft - FuncWindow->LeftEdge,
set->FuncWinTop - FuncWindow->TopEdge);
break;
case CMD_SETPOS:
success = ParseTwoNums(param, &set->SetupWinLeft,
&set->SetupWinTop);
if (success && mode != MODE_SETTINGS && SetWindow)
MoveWindow(SetWindow, set->SetupWinLeft - SetWindow->LeftEdge,
set->SetupWinTop - SetWindow->TopEdge);
break;
case CMD_TASKPRI:
val = atoi(param);
if ((val == 0 && *param != '0') || val < -20 || val > 20)
return (EXEC_FAIL);
SetTaskPri(SysBase->ThisTask, val);
if (MainWindow)
SetMenuOptions();
break;
case CMD_CLEARBUFFER:
ClearWindowBuffer();
break;
case CMD_GOTO:
val = atoi(param);
if (val != 0) {
val += BaseSeq; /* Get real start position */
if (val > TopSeq)
DoArrowScrolling(GID_DOWNARROW, val - TopSeq);
else
DoArrowScrolling(GID_UPARROW, TopSeq - val);
} else
success = EXEC_FAIL;
break;
case CMD_SCROLLUP:
case CMD_SCROLLDOWN:
val = atoi(param);
if (!val)
val = 1;
if (cid == CMD_SCROLLUP)
DoArrowScrolling(GID_UPARROW, val);
else
DoArrowScrolling(GID_DOWNARROW, val);
break;
}
return (success ? EXEC_OKAY : EXEC_FAIL);
}
/*
* GetFontDesc(fontdesc, fontname, size)
*
* Builds a a string from the supplied fontname and size and stores
* it in fontdesc. Returns a pointer to the new string.
*
* For example, name="courier.font" and size=13 will return the
* string "courier 13";
*
* In the event that the fontname is invalid, the string "Default"
* is returned instead.
*/
char *GetFontDesc(char *fontdesc, char *fontname, int size)
{
char *p;
if (!fontname || !*fontname)
return ("Default");
strcpy(fontdesc, fontname);
p = strchr(fontdesc, '.');
if (!p)
p = fontdesc + strlen(fontdesc);
mysprintf(p, " %ld", size);
return (fontdesc);
}
/*
* SaveConfig(filename, saveicon)
*
* Writes the current configuration to the named disk file. Returns
* 1 for success, 0 for failure.
*
* saveicon is SAVE_ICON if an icon should be saved and CreateIcos
* is true, or SAVE_NOICON if an icon should never be saved.
*/
int SaveConfig(char *filename, int saveicon)
{
char tempdesc[MAX_SHORT_LEN];
SetupSettings *setup = &CurSettings.Setup;
BPTR file;
int i;
mysprintf(StatusLineText, MSG(MSG_STATUS_SAVESET), filename);
ShowStatus(StatusLineText);
DisableAllWindows();
RecordWindowSizes();
file = Open(filename, MODE_NEWFILE);
if (!file) {
EnableAllWindows();
UpdateStatus();
return (0);
}
FPrintf(file, "%s\n;\n; %s\n;\n; Settings file\n;\n",
ConfigID, Version);
#define NM(x) CmdNames[CMD_##x]
#define PF1(s,p) FPrintf(file, s, p)
#define PF2(s,p1,p2) FPrintf(file, s, p1, p2)
/*
* First of all, write out the function settings
*/
for (i = 1; i <= MAX_BOOL_CMD; i++) {
if (*CmdNames[i]) {
if (CurSettings.Func.Opts[i])
PF1("%s\n", CmdNames[i]);
else
PF1("No%s\n", CmdNames[i]);
}
}
/*
* Now write out all the variable settings
*/
PF2(";\n%s=\"%s\"\n",NM(MATCHNAME), CurSettings.Func.Pattern);
PF2("%s=%s\n", NM(HIDEMETHOD), Names_HideMethod[setup->HideMethod]);
PF2("%s=%s\n", NM(SCREENTYPE), Names_ScreenType[setup->ScreenType]);
PF2("%s=%s\n", NM(LOGMODE), Names_LogMode[setup->LogMode]);
PF2("%s=%s\n", NM(FILEIOTYPE), Names_FileIOType[setup->FileIOType]);
PF2("%s=%ld\n", NM(BUFFERSIZE), setup->BufferSize);
PF2("%s=\"%s\"\n", NM(HOTKEY), setup->HotKey);
PF2("%s=\"%s\"\n", NM(SCREENNAME), setup->ScreenName);
PF2("%s=\"%s\"\n", NM(LOGNAME), setup->LogFile);
PF2("%s=\"%s\"\n", NM(WINDOWFONT), GetFontDesc(tempdesc,
setup->WindowFont,
setup->WinFontSize));
PF2("%s=\"%s\"\n", NM(BUFFERFONT), GetFontDesc(tempdesc,
setup->BufferFont,
setup->BufFontSize));
PF2("%s=\"%s\"\n", NM(FORMAT), setup->BufferFormat);
PF2("%s=\"%s\"\n", NM(LOGFORMAT), setup->LogfileFormat);
PF2("%s=%ld\n", NM(TEXTSPACING), CurSettings.TextSpacing);
PF1("%s\n", CurSettings.SimpleRefresh ? NM(SIMPLEREFRESH) :
NM(SMARTREFRESH));
PF1("%s\n", CurSettings.RightAlign ? NM(RIGHTALIGNED) :
NM(LEFTALIGNED));
PF2("%s=%s\n", NM(ROWQUALIFIER), Names_RowQualifier[RowQual]);
PF1("%s\n", CurSettings.ShowStatus ? NM(SHOWSTATUS) :
NM(HIDESTATUS));
PF1("%s\n", CurSettings.ShowGadgets ? NM(SHOWGADGETS) :
NM(HIDEGADGETS));
PF2("%s%s\n", (AutoOpen ? "" : "No"), NM(AUTOOPEN));
PF2("%s%s\n", (DisableOnHide ? "" : "No"), NM(DISABLEWHENHIDDEN));
PF2("%s%s\n", (CurSettings.MakeIcons ? "" : "No"), NM(CREATEICONS));
FPrintf(file, "%s=%ld,%ld\n", NM(MAINPOS), CurSettings.MainWinLeft,
CurSettings.MainWinTop);
FPrintf(file, "%s=%ld,%ld\n", NM(MAINSIZE), CurSettings.MainWinWidth,
CurSettings.MainWinHeight);
FPrintf(file, "%s=%ld,%ld\n", NM(FORMPOS), CurSettings.FormWinLeft,
CurSettings.FormWinTop);
FPrintf(file, "%s=%ld,%ld\n", NM(FUNCPOS), CurSettings.FuncWinLeft,
CurSettings.FuncWinTop);
FPrintf(file, "%s=%ld,%ld\n", NM(SETPOS), CurSettings.SetupWinLeft,
CurSettings.SetupWinTop);
FPrintf(file, "%s=%ld,%ld\n", NM(ICONPOS), CurSettings.IconPosLeft,
CurSettings.IconPosTop);
FPrintf(file, "%s=%ld\n", NM(STACKLIMIT), CurSettings.StackLimit);
FPrintf(file, "%s=%ld\n", NM(TASKPRI),
SysBase->ThisTask->tc_Node.ln_Pri);
Close(file);
if (CreateIcons && saveicon != SAVE_NOICON)
WriteIcon(filename);
EnableAllWindows();
UpdateStatus();
GotLastSaved = 1; /* Indicate "Last Saved" can now be performed */
return (1);
}
/*
* LoadConfig(filename, mode, set)
*
* Attempts to load the specified configuration file into memory.
* Returns 1 for success (having executed all the commands, and updated
* windows etc. as appropriate) or 0 for failure (couldn't open file).
*
* To prevent infinite loops, we only allow three levels of nested
* configuration files (i.e. a maximum of three recursive calls to
* LoadConfig)
*
* Normally, set is NULL. If non-NULL, then it represents a set
* of settings currently being updated. In this case, LoadConfig
* doesn't actually install the new settings when it's finished
* reading them, it merely updates the values in set with the
* new values and relies on the caller to set them later on.
*
* The mode parameter indicates how we are being called -- from
* the CLI, Workbench, ARexx or internally. This is used to determine
* how error messages should be displayed (currently, messages will
* only be displayed in a CLI window).
*
* New: we now support reading from an interactive file (CON:....)
* This allows the user to open a command window by trying to load
* a suitable CON: specification. Commands will be executed as soon
* as they arrive, and settings will be updated immediately.
*/
int LoadConfig(char *filename, int mode, Settings *set)
{
static int nestcount;
Settings newsettings;
Settings *myset;
int interactive;
int linenum = 0;
int retvalue = EXEC_FAIL;
BPTR errorfile = NULL;
BPTR file;
char linebuf[200];
if (set == NULL) {
myset = &newsettings;
*myset = CurSettings;
UpdateFlags = 0;
} else {
myset = set;
}
if (nestcount >= MAX_LOAD_NESTING)
return (EXEC_FAIL);
nestcount++;
DisableAllWindows();
mysprintf(StatusLineText, MSG(MSG_STATUS_LOADSET), filename);
ShowStatus(StatusLineText);
file = Open(filename, MODE_OLDFILE);
if (!file)
goto abort_load;
/*
* If we're executing this command from a CLI, then display
* error messages in the CLI window, else don't display them
* at all.
*/
if (mode == MODE_CMDLINE)
errorfile = Output();
interactive = IsInteractive(file);
if (interactive) {
errorfile = file; /* Send errors to the command window */
} else {
/*
* If we're not loading settings from an interactive
* window, then check that the first line of the file
* contains the settings file identifier
*/
if (!FGets(file, linebuf, 199) ||
strnicmp(linebuf, ConfigID, strlen(ConfigID)) != 0)
{
goto abort_load;
}
linenum++;
}
/*
* Now read in lines from the command file and execute them.
*/
if (interactive) {
FPrintf(errorfile, "%s%s", MSG(MSG_CMD_HEADER), MSG(MSG_CMD_PROMPT));
Flush(errorfile);
}
while (FGets(file, linebuf, 199) != NULL) {
char *cmdline = linebuf;
char *q;
int result;
linenum++;
for (q = cmdline; *q && *q != '\n'; q++)
;
if (*q)
*q++ = '\0';
while (*cmdline == ' ' || *cmdline == '\t')
cmdline++;
if (!*cmdline || *cmdline == ';')
continue; /* Skip over lines with no text on them */
if (stricmp(cmdline, "exit") == 0) /* Skip rest of file */
break;
if (interactive && *cmdline == '?') {
ShowCommands(errorfile);
goto show_prompt;
}
/*
* Now execute the command ... interactive commands are
* executed internally, to allow QUIT to be executed.
*/
result = ExecCommand(cmdline,
(interactive ? MODE_INTERNAL : MODE_SETTINGS),
myset);
if (QuitFlag)
break;
if (result == EXEC_OKAY) {
if (interactive) {
/*
* For interactive commands, we update the
* settings at each step along the way so
* the user can see them taking effect.
*/
InstallSettings(myset, UpdateFlags);
UpdateFlags = 0;
*myset = CurSettings;
}
} else if (errorfile) {
int msgid;
switch (result) {
case EXEC_UNKNOWN: msgid = MSG_CMD_UNKNOWN; break;
case EXEC_FAIL: msgid = MSG_CMD_FAIL; break;
case EXEC_NOPARAM: msgid = MSG_CMD_NOPARAM; break;
}
if (!interactive)
FPrintf(errorfile, "%s, line %ld: ", filename, linenum);
FPrintf(errorfile, MSG(msgid), cmdline);
}
show_prompt:
if (interactive) {
FPrintf(errorfile, MSG(MSG_CMD_PROMPT));
Flush(errorfile);
}
}
retvalue = EXEC_OKAY;
if (interactive) {
/*
* For interactive use, we clear any CTRL-C typed by
* the user during usage; this avoids confusion since
* the CTRL-C wouldn't have taken effect immediately
* anyway.
*/
CheckSignal(SIGBREAKF_CTRL_C);
}
/*
* If we just successfully loaded a file, it was probably the
* defaults file, so enable the "Last Saved" menu option (if it's
* not enabled, then it doesn't try to load a file since there was
* no file ever saved).
*/
GotLastSaved = 1;
abort_load:
if (file)
Close(file);
nestcount--;
if (set == NULL)
InstallSettings(myset, UpdateFlags);
UpdateStatus();
EnableAllWindows();
return (retvalue);
}
/*
* InitRexxPort
*
* Attempts to create SnoopDos's public port and initialise SnoopPort
* and RexxPortMask accordingly. If the port already exists, still
* returns TRUE but SnoopPort will be NULL.
*
* If we can't create the port for some reason, returns FALSE.
*/
int InitRexxPort(void)
{
struct MsgPort *port;
Forbid();
port = FindPort(PORT_NAME);
if (!port) {
SnoopPort = CreateMsgPort();
if (!SnoopPort) {
Permit();
return (FALSE);
}
SnoopPort->mp_Node.ln_Name = PORT_NAME;
SnoopPort->mp_Node.ln_Pri = 1; /* Speed up searches */
AddPort(SnoopPort);
RexxPortMask = 1 << SnoopPort->mp_SigBit;
}
Permit();
return (TRUE);
}
/*
* CleanupRexxPort()
*
* Cleans up our SnoopDos port -- removes it from the public port
* list, and then replies to any messages it has outstanding. Call
* before exiting.
*/
void CleanupRexxPort(void)
{
if (SnoopPort) {
struct RexxMsg *msg;
Forbid();
RemPort(SnoopPort);
while ((msg = (struct RexxMsg *)GetMsg(SnoopPort)) != NULL) {
msg->rm_Result1 = RC_FATAL;
msg->rm_Result2 = NULL;
ReplyMsg(msg);
}
Permit();
DeleteMsgPort(SnoopPort);
SnoopPort = NULL;
}
if (RemoteReplyPort) {
DeleteMsgPort(RemoteReplyPort);
RemoteReplyPort = NULL;
}
}
/*
* HandleRexxMsgs()
*
* Handles any new messages at our Rexx port
*/
void HandleRexxMsgs(void)
{
Settings newsettings = CurSettings;
struct RexxMsg *msg;
UpdateFlags = 0;
while ((msg = (struct RexxMsg *)GetMsg(SnoopPort)) != NULL) {
msg->rm_Result1 = RC_OK;
msg->rm_Result2 = NULL;
if ((msg->rm_Action & RXCODEMASK) == RXCOMM) {
/*
* Got a valid ARexx message, now process it
*/
switch (ExecCommand(msg->rm_Args[0], MODE_REXX, &newsettings)) {
/*
* See include:rexx/errors.h for the meanings of
* these Rexx return codes
*/
case EXEC_NOPARAM: msg->rm_Result1 = 10; break;
case EXEC_FAIL: msg->rm_Result1 = 20; break;
case EXEC_UNKNOWN: msg->rm_Result1 = 30; break;
}
}
ReplyMsg(msg);
}
InstallSettings(&newsettings, UpdateFlags);
}
/*
* SendRemote(cmdline, mode)
*
* Sends a command to a remote copy of SnoopDos running in the
* background. The mode is MODE_CMDLINE or MODE_TOOLTYPE. The
* difference is that for MODE_TOOLYPE, HIDE commands are ignored.
*
* In both cases, the command is first checked against the command
* table to make sure it's valid. If it's invalid, then if the mode
* is MODE_CMDLINE, an appropriate error message is printed.
*/
void SendRemote(char *cmdline, int mode)
{
struct Command *cmd;
struct MsgPort *ourport;
char cmdname[100];
char param[100];
int boolvalue;
int cid;
cid = ParseCommand(cmdline, cmdname, param, &boolvalue, &cmd);
switch (cid) {
case CMD_UNKNOWN:
if (mode == MODE_CMDLINE)
Printf(MSG(MSG_ERROR_CLI_UNKNOWN), cmdline);
return;
case CMD_NOPARAM:
if (mode == MODE_CMDLINE)
Printf(MSG(MSG_ERROR_CLI_NOPARAM), cmdline);
return;
case CMD_HIDE:
/*
* Don't send a HIDE command to the current SnoopDos if
* it was in an icon's tooltypes
*/
if (mode == MODE_TOOLTYPE)
return;
break;
case CMD_END:
return;
}
/*
* Got a command that's okay to send. Now locate SnoopDos port
* and send it. We have to locate the port each time, in case
* the user quits the background copy suddenly.
*/
if (!RemoteReplyPort) {
RemoteReplyPort = CreateMsgPort();
if (!RemoteReplyPort)
return;
}
Forbid();
ourport = FindPort(PORT_NAME);
if (ourport) {
struct RexxMsg msg;
msg.rm_Action = RXCOMM;
msg.rm_Args[0] = cmdline;
msg.rm_Node.mn_ReplyPort = RemoteReplyPort;
PutMsg(ourport, &msg);
WaitPort(RemoteReplyPort);
GetMsg(RemoteReplyPort);
Permit();
if (mode == MODE_CMDLINE && msg.rm_Result1 >= RC_ERROR)
Printf(MSG(MSG_ERROR_CLI_FAILED), cmdline);
} else
Permit();
}
/*
* ShowCommands(file)
*
* Prints a neatly formatted list of recognised commands to
* the specified output file.
*/
void ShowCommands(BPTR file)
{
int i;
int numrows = (NUM_CMDNAMES + 3) / 4;
FPrintf(file, MSG(MSG_CLI_HELPBANNER));
for (i = 0; i < numrows; i++) {
int j;
if (CheckSignal(SIGBREAKF_CTRL_C)) {
FPrintf(file, "^C\n");
break;
}
for (j = i; j < NUM_CMDNAMES; j += numrows) {
char *pmsg = (CommandTable[j].numparms > 0) ? "*" : " ";
char *cmsg = CommandTable[j].name;
if (j < (NUM_CMDNAMES - numrows))
FPrintf(file, "%s%-18s", pmsg, cmsg);
else
FPrintf(file, "%s%s", pmsg, cmsg);
}
FPrintf(file, "\n");
}
}
/*
* ParseStartupOpts()
*
* Handles the startup options, either on the command line or via
* the tooltypes, and sets the default options accordingly.
*
* We handle a couple of options specially (LOCALE and SETTINGS) since
* these must be set before doing anything else at all (we can't even
* print a meaningful error message without LOCALE, for example.)
*
* After those, we read in our configuration file from disk, and then
* parse the remaining items which can thus override any of the options
* specified in the config file. This applies even to tooltypes, so if
* an icon has a certain option hardcoded into it, this will always
* override a config file with the same option set.
*
* Normally, CLI and Tooltype options are only used to control things
* like opening a default logfile, set the Commodity priority or config
* file name, making SnoopDos start in the background, or automatically
* opening one or more windows.
*
* As a final step, if we spot that we are not the main instance of
* SnoopDos, we send all the new commands to the background copy instead.
* We also signal the background copy to come to the foreground by
* default (Workbench) or if no other options are specified (CLI).
*
* Returns TRUE for success, FALSE for failure.
*
*/
int ParseStartupOpts(int argc, char **argv)
{
struct Settings newset = DefaultSettings;
struct DiskObject *IconCache[20];
struct DiskObject *dobj = NULL;
struct WBArg *wbarg;
char msg[200];
int success = 1;
int maxargs;
int i;
int gotsettings = 0; /* If true, settings keyword specified */
/*
* We start off in a special disabled state (not 0, not 1)
* to ensure no events get monitored during our initialisation.
* We use a special state so that we can detect if the user
* specifies Disabled = Yes/No during startup.
*/
Disabled = 2; /* Start up in disabled state */
if (WBenchMsg) {
/*
* Starting up from Workbench.
*/
if (!IconBase)
return (FALSE);
maxargs = min(WBenchMsg->sm_NumArgs, 20);
for (i = 0, wbarg = WBenchMsg->sm_ArgList; i < maxargs; i++, wbarg++) {
BPTR olddir;
IconCache[i] = NULL;
if (wbarg->wa_Lock && *wbarg->wa_Name) {
olddir = CurrentDir(wbarg->wa_Lock);
dobj = GetDiskObject(wbarg->wa_Name);
if (dobj) {
char *param;
param = FindToolType(dobj->do_ToolTypes,
CmdNames[CMD_SETTINGS]);
if (param && *param) {
strcpy(DefaultConfigName, param);
gotsettings = 1;
}
param = FindToolType(dobj->do_ToolTypes,
CmdNames[CMD_LANGUAGE]);
if (param && *param)
strcpy(Language, param);
param = FindToolType(dobj->do_ToolTypes,
CmdNames[CMD_PATCHRAMLIB]);
if (param && stricmp(param, "no") == 0)
NoPatchRamLib = 1;
IconCache[i] = dobj;
}
CurrentDir(olddir);
}
}
} else {
/*
* Starting up from the CLI so scan the command line using
* the passed-in arguments.
*/
if (argc > 1) {
if (argv[1][0] == '-' || argv[1][0] == '?') {
Printf(MSG(MSG_CLI_USAGE), CommodityTitle, argv[0]);
return (FALSE);
}
}
/*
* Do a prescan of the command line looking
* for SETTINGS, LANGUAGE or PATCHRAMLIB, keywords.
*/
for (i = 1; i < argc; i++) {
char cmdname[50];
char param[150];
char newcmd[200];
int boolvalue;
struct Command *cmd;
int cid;
cid = ParseCommand(argv[i], cmdname, param, &boolvalue, &cmd);
if (cid == CMD_NOPARAM && ((i + 1) < argc)) {
/*
* Indicates we didn't get enough parameters for our
* command. Let's grab the next option off the command
* line instead and see if that makes sense.
*/
mysprintf(newcmd, "%s %s", argv[i], argv[i+1]);
cid = ParseCommand(newcmd, cmdname, param, &boolvalue, &cmd);
i++; /* Skip over next parameter */
}
switch (cid) {
case CMD_SETTINGS:
strcpy(DefaultConfigName, param);
gotsettings = 1;
break;
case CMD_LANGUAGE:
strcpy(Language, param);
break;
case CMD_PATCHRAMLIB:
NoPatchRamLib = !boolvalue;
break;
}
}
}
/*
* Now initialise locale according to the language chosen,
* and read in our default configuration file.
*/
InitLocale(Language);
InitMenus();
/*
* Note that LoadConfig() and further ExecCommand() calls may
* cause the settings to be installed at any time, and UpdateFlags
* to be reset to null. Thus, it is important to ensure that
* we initialise them correctly in the first place.
*/
UpdateFlags = SET_ALL;
if (SnoopPort) {
/*
* We only initialise our patches if we're the only task
* running at the moment. We leave the initialisation
* until now so that we can control whether or not our
* ramlib patch gets installed.
*/
if (!InitPatches()) {
if (WBenchMsg)
ShowError(MSG(MSG_ERROR_INITPATCHES));
else
Printf("%s\n", MSG(MSG_ERROR_INITPATCHES));
Cleanup(40);
}
if (!gotsettings) {
/*
* If we haven't yet got a settings file, then try a number of
* possible locations (in order of priority). If we find a
* match, we overwrite the default config name with the new
* name, for future use by LoadConfig and SaveConfig.
*/
static char *defconfig[] = {
"PROGDIR:" SETTINGS_BASENAME,
"S:" SETTINGS_BASENAME,
"ENVARC:" SETTINGS_BASENAME,
NULL
};
APTR oldwinptr = *TaskWindowPtr;
char **pdefname;
*TaskWindowPtr = (APTR)-1;
for (pdefname = defconfig; *pdefname; pdefname++) {
BPTR lk = Lock(*pdefname, ACCESS_READ);
if (lk) {
UnLock(lk);
break;
}
}
if (!*pdefname) {
/*
* Choose a good default name. We try for ENVARC:
* initially, but if that fails, fall back on S:
*/
if (IsFileSystem(defconfig[2]))
pdefname = &defconfig[2];
else
pdefname = &defconfig[1];
}
strcpy(DefaultConfigName, *pdefname);
strcpy(ConfigFileName, *pdefname);
*TaskWindowPtr = oldwinptr;
} else {
/*
* Do a quick check to see if the filename specified
* using the Settings keyword exists -- if it doesn't,
* then don't bother to try loading it (this avoids
* a requester being shown unnecessarily).
*/
BPTR lk = Lock(DefaultConfigName, ACCESS_READ);
if (lk)
UnLock(lk);
else
gotsettings = 0;
}
/*
* Now, one way or another, we have the default config filename
* set up so try and load it.
*/
if (!LoadConfig(DefaultConfigName,
(WBenchMsg ? MODE_TOOLTYPE : MODE_CMDLINE), &newset)
&& gotsettings)
{
ShowError(MSG(MSG_ERROR_LOADING_SETTINGS), DefaultConfigName);
}
}
/*
* Finally, lets parse the remaining startup options and/or icons
*/
if (WBenchMsg) {
/*
* Scan all the config files (if any) that were passed as
* parameters via icons.
*/
wbarg = WBenchMsg->sm_ArgList + 1;
for (i = 1; i < WBenchMsg->sm_NumArgs; i++, wbarg++) {
char *name = wbarg->wa_Name;
if (SnoopPort) {
BPTR olddir = CurrentDir(wbarg->wa_Lock);
LoadConfig(name, MODE_INTERNAL, &newset);
CurrentDir(olddir);
} else {
/*
* There's a background copy running so we need
* to tell it to load the config file instead.
*/
char *p;
mysprintf(msg, "%s ", CmdNames[CMD_LOADSETTINGS]);
p = msg + strlen(msg);
NameFromLock(wbarg->wa_Lock, p, 150);
AddPart(p, wbarg->wa_Name, 150);
SendRemote(msg, MODE_TOOLTYPE);
}
}
/*
* Rescan the icons, this time processing all the tooltypes that
* we recognise. Any we don't recognise are ignored. SETTINGS
* command may get parsed a second time, but that's okay.
*/
for (i = 0; i < maxargs; i++) {
dobj = IconCache[i];
if (dobj) {
char **tooltypes;
for (tooltypes = dobj->do_ToolTypes; *tooltypes; tooltypes++) {
if (SnoopPort)
ExecCommand(*tooltypes, MODE_TOOLTYPE, &newset);
else
SendRemote(*tooltypes, MODE_TOOLTYPE);
}
FreeDiskObject(dobj);
}
}
if (!SnoopPort)
SendRemote(CmdNames[CMD_SHOW], MODE_CMDLINE);
} else {
/*
* Do a proper scan of the CLI arguments.
*/
for (i = 1; i < argc; i++) {
char newcmd[200];
char *thiscmd = argv[i];
struct Command *cmd;
int boolvalue;
int cid;
/*
* Check if the command we're checking needs more than
* one parameter. If so, and if it wasn't supplied, we
* assume that the parameter after it on the command
* line is to be used. This means the user doesn't have
* to specifically type the '='.
*
* HELP is a special case, since HELP will work with zero
* parameters too. We only try and handle help if there
* is at least one more parameter after it on the command
* line. If there isn't, then we print a list of supported
* commands instead.
*/
cid = ParseCommand(thiscmd, newcmd, newcmd+50, &boolvalue, &cmd);
if ( (i+1) < argc && (cid == CMD_HELP ||
(cid == CMD_NOPARAM && cmd->numparms > 0)) )
{
/*
* We didn't have a parameter for this command, so
* assume the next parameter on the command line is
* the parameter instead.
*/
mysprintf(newcmd, "%s %s", argv[i], argv[i+1]);
thiscmd = newcmd;
i++;
} else if (cid == CMD_HELP) {
/*
* Didn't have anything following the HELP so
* print CLI help instead and exit immediately.
*/
ShowCommands(Output());
return (0);
}
if (SnoopPort) {
switch (ExecCommand(thiscmd, MODE_CMDLINE, &newset)) {
case EXEC_FAIL:
Printf(MSG(MSG_ERROR_CLI_FAILED), thiscmd);
success = 0;
break;
case EXEC_NOPARAM:
Printf(MSG(MSG_ERROR_CLI_NOPARAM), thiscmd);
success = 0;
break;
case EXEC_UNKNOWN:
Printf(MSG(MSG_ERROR_CLI_UNKNOWN), thiscmd);
success = 0;
break;
// case EXEC_OKAY:
}
} else {
SendRemote(thiscmd, MODE_CMDLINE);
}
}
if (!SnoopPort && argc == 1)
SendRemote(CmdNames[CMD_SHOW], MODE_CMDLINE);
}
if (!SnoopPort)
success = 0;
/*
* Now check if the user specified Disable=YES (or NO) during
* startup. If they didn't, then reset the disable flag.
* Regardless, we want to update the function flags to reflect
* the current disable state.
*/
if (Disabled == 2)
SetMonitorMode(MONITOR_NORMAL);
if (success)
InstallSettings(&newset, UpdateFlags | SET_FUNC);
return (success);
}